package com.neusoft.neuiotms.dcam.fixed.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.google.common.collect.Maps;
import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.dcam.fixed.converter.InventoryResultConverter;
import com.neusoft.neuiotms.dcam.fixed.dto.InventoryResultDTO;
import com.neusoft.neuiotms.dcam.fixed.model.Asset;
import com.neusoft.neuiotms.dcam.fixed.model.InventoryResult;
import com.neusoft.neuiotms.dcam.fixed.model.enums.InventoryDutyResultStatus;
import com.neusoft.neuiotms.dcam.fixed.repository.AssetRepository;
import com.neusoft.neuiotms.dcam.fixed.repository.InventoryResultRepository;
import com.neusoft.neuiotms.dcam.fixed.service.InventoryResultService;

@Service
@Transactional
public class InventoryResultServiceImpl implements InventoryResultService {

    @Autowired
    private InventoryResultRepository inventoryDutyResultRepository;
    @Autowired
    private InventoryResultConverter inventoryDutyResultConverter;
    @Autowired
    private AssetRepository assetRepository;

    @Override
    public List<InventoryResultDTO> findAll(final Searchable searchable) {
        final List<InventoryResult> models = this.inventoryDutyResultRepository.search(searchable);
        final List<InventoryResultDTO> listData = this.inventoryDutyResultConverter.toListDTO(models);

        final List<Asset> allAssetList = this.assetRepository.findAll();
        final Map<String, Asset> assetMap = Maps.newHashMap();
        allAssetList.stream().forEach(it -> {
            assetMap.put(it.getCode(), it);
        });
        listData.forEach(d -> {
            //            final Asset asset = this.assetRepository.findByCode(d.getCode());
            final Asset mAsset = assetMap.get(d.getCode());
            if (null != mAsset) {
                d.setComputerRoom(mAsset.getComputerRoom());
                d.setCabinet(mAsset.getCabinet());
            }
        });
        return listData;
    }

    @Override
    public Page<InventoryResultDTO> search(final Pageable pageable, final Searchable searchable) {
        final Page<InventoryResult> models = this.inventoryDutyResultRepository.search(pageable, searchable);
        final Page<InventoryResultDTO> pageData = this.inventoryDutyResultConverter.toPageDTO(models);
        pageData.getContent().forEach(d -> {
            final Asset asset = this.assetRepository.findByCode(d.getCode());
            d.setComputerRoom(asset.getComputerRoom());
            d.setCabinet(asset.getCabinet());

        });
        return pageData;
    }

    @Override
    public InventoryResultDTO create(final InventoryResultDTO dto) {

        InventoryResult model = this.inventoryDutyResultConverter.toModel(dto);
        model = this.inventoryDutyResultRepository.save(model);

        return this.inventoryDutyResultConverter.toDTO(model);
    }

    @Override
    public InventoryResultDTO details(final Long id) {

        final InventoryResult model;
        try {
            model = this.inventoryDutyResultRepository.getOne(id);
        } catch (final Exception e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        return this.inventoryDutyResultConverter.toDTO(model);
    }

    @Override
    public InventoryResultDTO update(final Long id, final InventoryResultDTO dto) {

        InventoryResult model;
        try {
            model = this.inventoryDutyResultRepository.getById(id); // getOne(id);
        } catch (final Exception e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        dto.setId(model.getId());
        model = this.inventoryDutyResultConverter.toModel(dto);

        // 变更
        this.inventoryDutyResultRepository.save(model);

        return this.inventoryDutyResultConverter.toDTO(model);
    }

    @Override
    public void updateStatus(final Long id, final InventoryDutyResultStatus status) {

        InventoryResult model;
        try {
            model = this.inventoryDutyResultRepository.getOne(id);
        } catch (final Exception e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        model.setDutyResultStatus(status);
        model.setUpdateTime(new Date());

        this.inventoryDutyResultRepository.save(model);
    }

    @Override
    public void delete(final Long id) {

        try {
            this.inventoryDutyResultRepository.getOne(id);
        } catch (final Exception e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        //        if (null != model.getAssetId()) {
        //            throw new UnitedException("只能删除新增的盘盈数据");
        //        }

        this.inventoryDutyResultRepository.deleteById(id);
    }

    @Override
    @Transactional
    public void synchronousData(final String ids, final String rule) {
        if (StringUtils.isEmpty(rule) || StringUtils.isEmpty(ids)) {
            return;
        }

        final String[] rules = rule.split(",");

        final List<Long> longArray = new ArrayList<>();
        final String[] idArray = ids.split(",");
        Arrays.asList(idArray).forEach(item -> longArray.add(Long.parseLong(item)));

        final Searchable searchable = new Searchable();
        // searchable.put("planId", planId);
        searchable.put("ids", longArray);
        final List<InventoryResultDTO> dtos = this.findAll(searchable);

        dtos.forEach(m -> {

            // 盘盈添加资产
            if (InventoryDutyResultStatus.gain.equals(m.getDutyResultStatus()) &&
                    Arrays.asList(rules).contains("1")) {
                //                final AssetDTO dto = this.inventoryDutyResultConverter.toDTO(m);
                //                final AssetDTO assetDTO = this.assetService.create(dto);
                //                m.setAssetId(assetDTO.getId());
                this.inventoryDutyResultRepository.save(this.inventoryDutyResultConverter.toModel(m));
            }

            // 盘亏删除资产
            else if (InventoryDutyResultStatus.loss.equals(m.getDutyResultStatus()) &&
                    Arrays.asList(rules).contains("3")) {
                //                if (null != m.getAssetId()) {
                //                    this.assetService.delete(m.getAssetId());
                //                }
            }

            // 其他是否修改了信息
            else if (Arrays.asList(rules).contains("2")) {
                //                if ((null != m.getAssetId())
                //                        && ((null != m.getUpdateUserId()) || !StringUtils.isEmpty(m.getUpdateOrgCode())
                //                                || (!StringUtils.isEmpty(m.getUpdateLocationCode())))) {
                //                    final AssetDTO dto = this.assetService.details(m.getAssetId());
                //
                //                    // 使用人变更
                //                    //                    if (null != m.getUpdateUserId()) {
                //                    //                        dto.setUserId(m.getUpdateUserId());
                //                    //                        dto.setUserName(m.getUpdateUserName());
                //                    //                    }
                //
                //                    // 组织变更
                //                    //                    if (!StringUtils.isEmpty(m.getUpdateOrgCode())) {
                //                    //                        dto.setOrgId(m.getUpdateOrgCode());
                //                    //                        dto.setOrgName(m.getUpdateOrgName());
                //                    //                    }
                //
                //                    // 位置变更
                //                    //                    if (!StringUtils.isEmpty(m.getUpdateLocationCode())) {
                //                    //                        dto.setLocationCode(m.getUpdateLocationCode());
                //                    //                        dto.setLocationName(m.getUpdateLocationName());
                //                    //                    }
                //
                //                    this.assetService.update(m.getAssetId(), dto);
                //                }
            }
        });
    }

    @Override
    public void update(List<Long> idArr, InventoryDutyResultStatus status) {
        final List<InventoryResult> list = this.inventoryDutyResultRepository.findByIdIn(idArr);
        list.forEach(it -> it.setDutyResultStatus(status));
        this.inventoryDutyResultRepository.saveAll(list);
    }

    @Override
    public void clearResults(Long dutyId) {
        this.inventoryDutyResultRepository.deleteByInventoryDuty_Id(dutyId);
    }

    @Override
    public void updatePan(Map<Long, Map<String, Object>> map) {
        final List<InventoryResult> models = Lists.newArrayList();
        //        final Date now = new Date();
        for (final Map.Entry<Long, Map<String, Object>> entry : map.entrySet()) {
            final long resultId = entry.getKey();

            final Optional<InventoryResult> opt = this.inventoryDutyResultRepository.findById(resultId);
            if (opt.isPresent()) {
                final InventoryResult model = opt.get();
                final String dutyResultStatus = (String) entry.getValue().get("dutyResultStatus");
                final String updateUserId = (String) entry.getValue().get("updateUserId");
                final String updateUserName = (String) entry.getValue().get("updateUserName");
                final String updateOrgCode = (String) entry.getValue().get("updateOrgCode");
                final String updateOrgName = (String) entry.getValue().get("updateOrgName");
                final String updateLocationCode = (String) entry.getValue().get("updateLocationCode");
                final String updateLocationName = (String) entry.getValue().get("updateLocationName");

                //                model.setUpdateTime(now);
                model.setDutyResultStatus(InventoryDutyResultStatus.valueOf(dutyResultStatus));
                model.setUpdateUserId(updateUserId);
                model.setUpdateUserName(updateUserName);
                model.setUpdateOrgCode(updateOrgCode);
                model.setUpdateOrgName(updateOrgName);
                model.setUpdateLocationCode(updateLocationCode);
                model.setUpdateLocationName(updateLocationName);
                models.add(model);
            }
        }

        if (models.size() > 0) {
            this.inventoryDutyResultRepository.saveAll(models);
        }

    }

}
